/**
 * \brief Implementação de uma hashMap.
 *
 * Segue a filosofia open adressing para resolver as colisões. 
 */
# ifndef OPEN_ADRESSING_HASHMAP
# define OPEN_ADRESSING_HASHMAP

# include <stdlib.h>
# include "hash.h"
# include "../lists/linked-list.h"

typedef enum { LINEAR, QUADRATIC } ProbingType;

typedef struct {
   int size;
   ProbingType type;
   HashMapElem **list;
   equalFunction eq;
   hashFunction hash;
} OpenAdressingHashMap;

/**
 * \brief Cria uma nova hash em memória. 
 * \param size 	O tamanho da hash (preferencialmente primo) 
 * \param type O tipo de probing (Linear ou Quadratico)
 * \return A nova Tabela
 *
 * É necessário no entanto definir as funções de Hash e Igualdade de chaves.
 */
OpenAdressingHashMap * newOpenAdressingHashMap (int size, ProbingType type);
/**
 * \brief Adiciona par (key,data) à tabela.
 * \param map Tabela
 * \param key Chave
 * \param Informação
 * \return 0 se não conseguir, 1 se conseguiu
 *
 * Pode crashar com o programa se não for possivel armazenar em memória um novo elemento hash. Não é necessário que a chave esteja contida na informação.
 */
int putOpenAdressing (OpenAdressingHashMap *map, void *key, void *data);
/**
 * \brief Da a informação contida no elemento com chave igual à dada.
 * \param map Tabela
 * \param key Chave
 * \return NULL se não tiver, ou elemento Da a informação contida no elemento com chave igual à dada.
 */
void * getOpenAdressing (OpenAdressingHashMap *map, void *key);

/**
 * \brief Lista de chaves da tabela
 * \param map Tabela
 * \return Lista de chaves
 */
LinkedList * keySetOpenAdressing (OpenAdressingHashMap *map);
# endif

